package com.fengdi.book.middle;

import java.util.HashMap;

public class DynamicProgram {
    public static class CanJump {
        public boolean canJump(int[] nums) {
            if(nums.length == 1) return true;
            if(nums[0] == 0) return false;

            int len = nums.length;
            int[] dp = new int[len];
            dp[0] = nums[0];
            for(int i = 1; i < nums.length; i++) {
                dp[i] = Math.max(dp[i - 1] - 1, nums[i]);
                if(i + dp[i] >= len - 1) {
                    return true;
                }else if(dp[i] == 0) {
                    return false;
                }
            }
            return false;
        }
    }

    public static class UniquePaths {
        // 回溯的方法可以得到正确答案，但是会超时
        public int uniquePaths(int m, int n) {
            int[][] dp = new int[m][n];
            dp[0][0] = 1;
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    if (i - 1 >= 0) {
                        dp[i][j] += dp[i - 1][j];
                    }
                    if (j - 1 >= 0) {
                        dp[i][j] += dp[i][j - 1];
                    }
                }
            }
            return dp[m - 1][n - 1];
        }
    }

    public static class CoinChange {
        public int coinChange(int[] coins, int amount) {
            int[] dp = new int[amount+1]; // dp[i] 表示凑成金额i所需要的最少硬币数
            dp[0] = 0;
            for(int i = 1; i <= amount; i++) {
                int min = Integer.MAX_VALUE;
                for(int c : coins) {
                    if(i - c >= 0) {
                        int tem = dp[i - c] == Integer.MAX_VALUE ? Integer.MAX_VALUE - 1: dp[i - c];
                        min = Math.min(min, dp[i - c] + 1);
                    }
                }
                dp[i] = min;
            }
            return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount];
        }
    }

    public static class LengthOfLIS {
        public int lengthOfLIS(int[] nums) {
            if(nums.length <= 1) return nums.length == 1 ? 1 : 0;

            int[] dp = new int[nums.length];
            int result = 1;
            dp[nums.length - 1] = 1;
            for(int i = nums.length - 2; i >= 0; i--) {
                int max = 0;
                for(int j = i + 1; j < nums.length; j++) {
                   if(nums[i] < nums[j]) {
                       max = Math.max(max, dp[j]);
                   }
                }
                dp[i] = max + 1;
                result = Math.max(result, dp[i]);
            }

            return result;
        }
    }

    public static class Divide {
        public int divide(int dividend, int divisor) {
            if (divisor == 0) return Integer.MAX_VALUE;
            boolean neg = (dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0);

            dividend =Math.abs(dividend);
            divisor = Math.abs(divisor);

            int result = 0;
            while (dividend >= divisor) {
                int temp = divisor;
                int count = 1;
                while(dividend >= (temp<<1)) {
                    temp <<= 1;
                    count <<= 1;
                }
                dividend = dividend - temp;
                result += count;
            }
            return neg ? -result : result;
        }
    }

    public static class fractionToDecimal {
        public String fractionToDecimal(int numerator, int denominator) {
            if (numerator == 0 || denominator == 1)return String.valueOf(numerator) ;
            long n = Math.abs((long)numerator);
            long d = Math.abs((long) denominator);
            StringBuilder sb = new StringBuilder();
            HashMap<Long,Integer> map = new HashMap<>();
            sb.append(n / d);
            long mo = n % d;
            if (mo != 0)sb.append(".");
            map.put(mo,sb.length());
            while (mo != 0){
                sb.append(mo * 10 / d);
                mo = mo * 10 % d;
                if (map.containsKey(mo)){
                    sb.insert(map.get(mo),"(");
                    sb.append(")");
                    break;
                }
                map.put(mo,sb.length());
            }
            return ( (numerator < 0 ^ denominator < 0)  ? "-" : "") + sb.toString();
        }
    }
}
